home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / Form / Sources / EditCmd.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  16.2 KB  |  512 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                EditCmd.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright:            (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "Form.hpp"
  11.  
  12. #ifndef EDITCMD_H
  13. #include "EditCmd.h"
  14. #endif
  15.  
  16. #ifndef FWEDVIEW_H
  17. #include "FWEdView.h"
  18. #endif
  19.  
  20. #ifndef FWFRAME_H
  21. #include "FWFrame.h"
  22. #endif
  23.  
  24. #ifndef FWPART_H
  25. #include "FWPart.h"
  26. #endif
  27.  
  28. #ifndef FWUTIL_H
  29. #include "FWUtil.h"
  30. #endif
  31.  
  32. #ifndef FWKIND_H
  33. #include "FWKind.h"
  34. #endif
  35.  
  36. #ifndef FWSUSINK_H
  37. #include "FWSUSink.h"
  38. #endif
  39.  
  40. #ifndef FWBARRAY_H
  41. #include "FWBArray.h"
  42. #endif
  43.  
  44. #ifndef FWSUUTIL_H
  45. #include "FWSUUtil.h"
  46. #endif
  47.  
  48. #ifndef SOM_Module_OpenDoc_Commands_defined
  49. #include "CmdDefs.xh"
  50. #endif
  51.  
  52. //========================================================================================
  53. // RunTime Info
  54. //========================================================================================
  55.  
  56. #ifdef FW_BUILD_MAC
  57. #pragma segment odfform
  58. #endif
  59.  
  60. FW_DEFINE_AUTO(CEditViewCommand)
  61.  
  62. //========================================================================================
  63. //    class FW_CEditViewCommand
  64. //========================================================================================
  65.  
  66. //----------------------------------------------------------------------------------------
  67. //    CEditViewCommand constructor
  68. //----------------------------------------------------------------------------------------
  69. CEditViewCommand::CEditViewCommand(Environment* ev, 
  70.                             ODCommandID commandID,
  71.                             FW_CFrame* frame,
  72.                             FW_Boolean canUndo)
  73. :    FW_CClipboardCommand(ev, commandID, frame, canUndo),
  74.     FW_MReceiver(),
  75.     fOwnsSelection(false),
  76.     fEditView(0),
  77.     fStartOffset(0),
  78.     fEndOffset(0)
  79. {
  80. }
  81.  
  82. //----------------------------------------------------------------------------------------
  83. //    CEditViewCommand destructor
  84. //----------------------------------------------------------------------------------------
  85.  
  86. CEditViewCommand::~CEditViewCommand()
  87. {
  88.     if (fOwnsSelection)
  89.         delete fSelection;        // Selection was created on the fly in DoMenu
  90. }
  91.  
  92. //----------------------------------------------------------------------------------------
  93. //    CEditViewCommand::SetEditView
  94. //----------------------------------------------------------------------------------------
  95. // SetEditView must be called right after the creation of the CEditViewCommand in order
  96. // to initialize the fEditView attribut because FW_CFrame::NewClipboardCommand doesn't let
  97. // us pass arguments.  See CScrollEdit::DoMenu().
  98.  
  99. void CEditViewCommand::SetEditView(FW_CEditView* editView)
  100. {
  101.     fEditView = editView;
  102.     
  103.     // [LSD] work-around to notify & disable the command when the edit view is deleted
  104.     // See CEditViewCommand::HandleNotification
  105.     AddInterest(FW_CInterest(editView, FW_kNotifierDeletedMsg));
  106. }
  107.  
  108. //----------------------------------------------------------------------------------------
  109. //    CEditViewCommand::HandleNotification
  110. //----------------------------------------------------------------------------------------
  111. // 
  112. void CEditViewCommand::HandleNotification(Environment* ev, const FW_CNotification& notification) 
  113. {
  114. FW_UNUSED(ev);
  115.     if (notification.GetMessage() == FW_kNotifierDeletedMsg)
  116.     {
  117.         // [LSD] The edit view associated with this command has been deleted.  We cannot
  118.         // delete the command ourselves, it belongs to OpenDoc Undo stack, but we must
  119.         // disable it to avoid any trouble in RedoIt & UndoIt.
  120.         fEditView = 0;
  121.     }
  122. }
  123.  
  124. //----------------------------------------------------------------------------------------
  125. //    CEditViewCommand::PreCommand
  126. //----------------------------------------------------------------------------------------
  127.  
  128. void CEditViewCommand::PreCommand(Environment* ev)
  129. {
  130.     ODCommandID id = GetCommandID(ev);
  131.     
  132.     if ((id == kODCommandCopy) || (id == kODCommandCut))
  133.         fEditView->DoTECommand(ev, kODCommandCopy, false);    // Tell TE to copy the text
  134. }
  135.  
  136. //----------------------------------------------------------------------------------------
  137. //    CEditViewCommand::CommandDone
  138. //----------------------------------------------------------------------------------------
  139. /*
  140. void CEditViewCommand::CommandDone(Environment* ev)
  141. {
  142.     // If fEditView belongs to your part's content you may want to notify it of the change
  143.     switch (GetCommandID(ev))
  144.     {
  145.         case kODCommandCut:
  146.         case kODCommandPaste:
  147.         case kODCommandClear:
  148.             fEditView->Notify(ev, CEditNotification(fEditView));
  149.     }
  150. }
  151. */
  152.  
  153. //----------------------------------------------------------------------------------------
  154. //    CEditViewCommand::SaveUndoState
  155. //----------------------------------------------------------------------------------------
  156. void CEditViewCommand::SaveUndoState(Environment* ev)
  157. {
  158.     switch (GetCommandID(ev))
  159.     {
  160.         case kODCommandCut:
  161.         case kODCommandClear:
  162.             fPastedText = fEditView->GetSelectedText(ev);
  163.             fEditView->GetSelectionRange(ev, fStartOffset, fEndOffset);
  164.             break;
  165.  
  166.         case kODCommandPaste:
  167.             fSavedText = fEditView->GetSelectedText(ev);
  168.             fEditView->GetSelectionRange(ev, fStartOffset, fEndOffset);
  169.             break;
  170.     }
  171. }
  172.  
  173. //----------------------------------------------------------------------------------------
  174. //    CEditViewCommand::SaveRedoState
  175. //----------------------------------------------------------------------------------------
  176. void CEditViewCommand::SaveRedoState(Environment* ev)
  177. {
  178.     if (GetCommandID(ev) == kODCommandPaste)
  179.     {
  180.         CEditViewSelContent* selContent = (CEditViewSelContent*)fSelection->GetSelectedContent(ev);
  181.         fPastedText = selContent->GetInternalizedText(ev);
  182.     }
  183. }
  184.  
  185. //----------------------------------------------------------------------------------------
  186. //    CEditViewCommand::UndoIt
  187. //----------------------------------------------------------------------------------------
  188.  
  189. void CEditViewCommand::UndoIt(Environment* ev)
  190. {
  191.     FW_CClipboardCommand::UndoIt(ev);    // call inherited
  192.  
  193.     // Don't do anything if command is disabled
  194.     if (fEditView == NULL)
  195.         return;
  196.         
  197.     switch (GetCommandID(ev))
  198.     {
  199.         case kODCommandCut:
  200.         case kODCommandClear:
  201.             this->RestoreText(ev);
  202.             break;
  203.  
  204.         case kODCommandPaste:
  205.             this->RemoveAndRestoreText(ev, fPastedText.GetByteLength(), fSavedText);
  206.             break;
  207.     }    
  208. }
  209.  
  210. //----------------------------------------------------------------------------------------
  211. //    CEditViewCommand::RedoIt
  212. //----------------------------------------------------------------------------------------
  213. void CEditViewCommand::RedoIt(Environment* ev)
  214. {
  215.     FW_CClipboardCommand::RedoIt(ev);    // call inherited
  216.  
  217.     // Don't do anything if command is disabled
  218.     if (fEditView == NULL)
  219.         return;
  220.  
  221.     switch (GetCommandID(ev))
  222.     {
  223.         case kODCommandCut:
  224.         case kODCommandClear:
  225.             this->RemoveText(ev);
  226.             break;
  227.  
  228.         case kODCommandPaste:
  229.             this->RemoveAndRestoreText(ev, fSavedText.GetByteLength(), fPastedText);
  230.             break;
  231.     }    
  232. }
  233.  
  234. //----------------------------------------------------------------------------------------
  235. //    CEditViewCommand::RemoveText
  236. //----------------------------------------------------------------------------------------
  237.  
  238. void CEditViewCommand::RemoveText(Environment* ev)
  239. {
  240.     FW_ASSERT(fEditView);
  241.  
  242.     fEditView->SelectText(ev, fStartOffset, fEndOffset);
  243.     fEditView->DoTECommand(ev, kODCommandClear, false);
  244.  
  245.     // If fEditView belongs to your part's content you may want to notify it of the change
  246. //    fEditView->Notify(ev, CEditNotification(fEditView));
  247. }
  248.  
  249. //----------------------------------------------------------------------------------------
  250. //    CEditViewCommand::RestoreText
  251. //----------------------------------------------------------------------------------------
  252.  
  253. void CEditViewCommand::RestoreText(Environment* ev)
  254. {
  255.     FW_ASSERT(fEditView);
  256.  
  257.     // Insert the saved text back into the EditView
  258.     fEditView->InsertText(ev, fPastedText, fStartOffset);
  259.  
  260.     // If fEditView belongs to your part's content you may want to notify it of the change
  261. //    fEditView->Notify(ev, CEditNotification(fEditView));   
  262. }
  263.  
  264. //----------------------------------------------------------------------------------------
  265. //    CEditViewCommand::RemoveAndRestoreText
  266. //----------------------------------------------------------------------------------------
  267.  
  268. void CEditViewCommand::RemoveAndRestoreText(Environment* ev, FW_ByteCount bytesToRemove,
  269.                                                 const FW_CString& textToRestore)
  270. {
  271.     FW_ASSERT(fEditView);
  272.  
  273.     // Remove designated text
  274.     fEditView->SelectText(ev, fStartOffset, fStartOffset+(short)bytesToRemove);
  275.     fEditView->DoTECommand(ev, kODCommandClear, false);
  276.  
  277.     // Restore the text
  278.     fEditView->InsertText(ev, textToRestore, fStartOffset);
  279.  
  280.     // If fEditView belongs to your part's content you may want to notify it of the change
  281. //    fEditView->Notify(ev, CEditNotification(fEditView));
  282. }
  283.  
  284. #pragma mark -
  285. //========================================================================================
  286. //    CLASS CEditViewSelection
  287. //========================================================================================
  288.  
  289. FW_DEFINE_AUTO(CEditViewSelection)
  290.  
  291. //---------------------------------------------------------------------------------------
  292. //    CEditViewSelection constructor
  293. //---------------------------------------------------------------------------------------
  294.  
  295. CEditViewSelection::CEditViewSelection(Environment* ev, FW_CEditView* editview) :
  296.     FW_CSelection(ev, false, false),
  297.     fSelectedContent(NULL)
  298. {
  299.     fSelectedContent = FW_NEW(CEditViewSelContent, (ev, editview));
  300. }
  301.  
  302. //---------------------------------------------------------------------------------------
  303. //    CEditViewSelection destructor
  304. //---------------------------------------------------------------------------------------
  305.  
  306. CEditViewSelection::~CEditViewSelection()
  307. {
  308.     delete fSelectedContent;
  309. }
  310.  
  311. //---------------------------------------------------------------------------------------
  312. //    CEditViewSelection::ClearSelection
  313. //---------------------------------------------------------------------------------------
  314.  
  315. void CEditViewSelection::ClearSelection(Environment* ev)
  316. {
  317.     fSelectedContent->ClearSelectedText(ev); 
  318. }
  319.  
  320. //---------------------------------------------------------------------------------------
  321. //    CEditViewSelection::CloseSelection
  322. //---------------------------------------------------------------------------------------
  323.  
  324. void CEditViewSelection::CloseSelection(Environment* ev)
  325. {
  326.     fSelectedContent->UnselectText(ev);
  327. }
  328.  
  329. //---------------------------------------------------------------------------------------
  330. //    CEditViewSelection::IsEmpty
  331. //---------------------------------------------------------------------------------------
  332.  
  333. FW_Boolean CEditViewSelection::IsEmpty(Environment* ev) const
  334. {
  335.     return fSelectedContent->IsEmpty(ev);
  336. }
  337.  
  338. //---------------------------------------------------------------------------------------
  339. //    CEditViewSelection::SelectAll
  340. //---------------------------------------------------------------------------------------
  341.  
  342. void CEditViewSelection::SelectAll(Environment* ev)
  343. {
  344. FW_UNUSED(ev);
  345.     // This function is handled by the current EditView
  346. }
  347.  
  348. #pragma mark -
  349. //========================================================================================
  350. //    CEditViewSelContent class
  351. //========================================================================================
  352.  
  353. FW_DEFINE_AUTO(CEditViewSelContent)
  354.  
  355. //----------------------------------------------------------------------------------------
  356. // CEditViewSelContent constructor
  357. //----------------------------------------------------------------------------------------
  358. CEditViewSelContent::CEditViewSelContent(Environment* ev, FW_CEditView* editview) :
  359.     FW_CContent(ev, editview->GetFrame(ev)->GetPart(ev)),
  360.     fEditView(editview)
  361. {
  362. }
  363.  
  364. //----------------------------------------------------------------------------------------
  365. // CEditViewSelContent destructor
  366. //----------------------------------------------------------------------------------------
  367.  
  368. CEditViewSelContent::~CEditViewSelContent()
  369. {
  370. }
  371.  
  372. //----------------------------------------------------------------------------------------
  373. // CEditViewSelContent::ExternalizeKind
  374. //----------------------------------------------------------------------------------------
  375. void CEditViewSelContent::ExternalizeKind(Environment* ev,
  376.                                     ODStorageUnit* storageUnit,
  377.                                     FW_CKind* kind,
  378.                                     FW_StorageKinds storageKind,
  379.                                     FW_CPromise* promise,
  380.                                     FW_CCloneInfo* cloneInfo)
  381. {
  382. FW_UNUSED(cloneInfo);
  383. FW_UNUSED(storageKind);
  384. FW_UNUSED(promise);
  385.  
  386.     if (kind->IsEqual(ev, 'TEXT', kODPlatformDataType))
  387.     {
  388.         // Externalize in order of fidelity: ODIText, 'TEXT'
  389.         FW_CString selectedText = fEditView->GetSelectedText(ev);
  390.  
  391. /* This doesn't work, because when I Internalize the text it's in the form:
  392.     length word, char, etc. 
  393.     where each character takes up a word instead of a byte.
  394.     // Write the selected string as an ODIText
  395.     ODSetITextProp(ev, storageUnit, kODPropContents, kODIntlText, selectedText.RevealODIText());
  396. */
  397.  
  398.         // Write the selected string in Mac 'TEXT' format
  399.         FW_PStorageUnitSink suSink(ev, storageUnit, kODPropContents, kind->GetType(ev));
  400.         FW_CWritableStream stream(suSink);
  401.         stream.Write(selectedText.RevealBuffer(), selectedText.GetByteLength());
  402.     }
  403. }
  404.  
  405. //----------------------------------------------------------------------------------------
  406. // CEditViewSelContent::Internalizekind
  407. //----------------------------------------------------------------------------------------
  408.  
  409. FW_Boolean CEditViewSelContent::InternalizeKind(Environment* ev,
  410.                                          ODStorageUnit* sourceSU, 
  411.                                          FW_CKind* kind,
  412.                                          FW_StorageKinds storageKind,
  413.                                          FW_CCloneInfo* cloneInfo)
  414. {
  415. FW_UNUSED(cloneInfo);
  416. FW_UNUSED(storageKind);
  417.     FW_ASSERT(fEditView);
  418.     
  419.     FW_Boolean internalized = false;
  420.  
  421.     if (kind->IsEqual(ev, 'TEXT', kODPlatformDataType))
  422.     {    
  423.         FW_CString selectedText;
  424.  
  425.         // Compute the maximum number of characters that can be added to the edit view
  426.         short startSel, endSel;
  427.         fEditView->GetSelectionRange(ev, startSel, endSel);
  428.         FW_ByteCount  notSelectedChars = fEditView->GetTextLength(ev) - (endSel - startSel);
  429.         if (notSelectedChars >= fEditView->GetMaxChars(ev))
  430.             return false;
  431.  
  432.         FW_ByteCount  maxChars = fEditView->GetMaxChars(ev) - notSelectedChars;
  433.  
  434.     /* See note in Externalize
  435.         // ODIText
  436.         if (FW_SUExistsThenFocus(ev, sourceSU, kODPropContents, kODIntlText))    
  437.             internalized = InternalizeIntlText(ev, sourceSU, selectedText);
  438.         else 
  439.     */
  440.         // 'TEXT'
  441.         if (FW_SUExistsThenFocus(ev, sourceSU, kODPropContents, kind->GetType(ev)))    
  442.             internalized = InternalizeText(ev, sourceSU, selectedText, maxChars);
  443.  
  444.         if (internalized)
  445.         {
  446.             fInternalizedText = selectedText;
  447.             fEditView->SetSelectedText(ev, selectedText);
  448.  
  449.     //        if (storageKind != FW_kPartStorage)  
  450.     //            fEditView->GetFrame(ev)->GetPart(ev)->PartChanged(ev);
  451.         }
  452.     }
  453.     
  454.     return internalized;
  455. }
  456.  
  457. //----------------------------------------------------------------------------------------
  458. // CEditViewSelContent::ClearSelectedText
  459. //----------------------------------------------------------------------------------------
  460.  
  461. void CEditViewSelContent::ClearSelectedText(Environment* ev)
  462. {
  463.     fEditView->SetSelectedText(ev, FW_CString());
  464. }
  465.  
  466. //----------------------------------------------------------------------------------------
  467. // CEditViewSelContent::UnselectText
  468. //----------------------------------------------------------------------------------------
  469.  
  470. void CEditViewSelContent::UnselectText(Environment* ev)
  471. {
  472.     fEditView->SelectText(ev, 0, 0);    // [LSD] should be at selStart
  473. }
  474.  
  475. //---------------------------------------------------------------------------------------
  476. //    CEditViewSelContent::IsEmpty
  477. //---------------------------------------------------------------------------------------
  478.  
  479. FW_Boolean CEditViewSelContent::IsEmpty(Environment* ev) const
  480. {
  481.     short startOffset, endOffset; 
  482.     fEditView->GetSelectionRange(ev, startOffset, endOffset);
  483.     return (startOffset == endOffset);
  484. }
  485.  
  486. //----------------------------------------------------------------------------------------
  487. //    InternalizeText
  488. //----------------------------------------------------------------------------------------
  489. // Global function to read text fro a storage unit
  490.  
  491. FW_Boolean InternalizeText(Environment* ev, 
  492.                             ODStorageUnit* storageUnit, 
  493.                             FW_CString& text, 
  494.                             FW_ByteCount  maxChars)
  495. {
  496.     FW_ByteCount textSize = storageUnit->GetSize(ev);
  497.     if (textSize == 0) 
  498.         return false;
  499.         
  500.     if (textSize > maxChars)
  501.         textSize = maxChars;
  502.         
  503.     FW_CByteArray byteArray;
  504.     storageUnit->GetValue(ev, textSize, byteArray);
  505. //    byteArray.CopyBuffer(&buffer, textSize);
  506.     
  507.     text = FW_CString((char *)byteArray.GetBuffer(), textSize);
  508.     
  509.     return true;
  510. }
  511.  
  512.